package com.thinkingcoder.tccache.core;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import com.thinkingcoder.tccache.core.operator.AbstractOperator;
import com.thinkingcoder.tccache.core.operator.CommonOperator;
import com.thinkingcoder.tccache.core.operator.HashOperator;
import com.thinkingcoder.tccache.core.operator.ListOperator;
import com.thinkingcoder.tccache.core.operator.SetOperator;
import com.thinkingcoder.tccache.core.operator.StringOperator;
import com.thinkingcoder.tccache.core.operator.ZSetOperator;

public class TcCache {

    ScheduledExecutorService scheduledExecutor;

    CommonOperator commonOperator = new CommonOperator();
    StringOperator stringOperator = new StringOperator();
    ListOperator listOperator = new ListOperator();
    HashOperator hashOperator = new HashOperator();
    SetOperator setOperator = new SetOperator();
    ZSetOperator zSetOperator = new ZSetOperator();

    public void start() {
        System.out.println(" ===> TcCache start...");
        scheduledExecutor = Executors.newSingleThreadScheduledExecutor();
        scheduledExecutor.scheduleAtFixedRate(AbstractOperator::updateTimestamp, 10, 10, TimeUnit.MILLISECONDS);
    }

    public void shutdown() {
        System.out.println(" ===> TcCache shutdown...");
        scheduledExecutor.shutdown();
        if (!scheduledExecutor.isTerminated()) {
            try {
                if (!scheduledExecutor.awaitTermination(3, TimeUnit.SECONDS)) {
                    scheduledExecutor.shutdownNow();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
                throw new RuntimeException(e);
            }
        }
    }

    // ================== 0.Common ==================
    public int exists(String... keys) {
        return commonOperator.exists(keys);
    }

    public int del(String... keys) {
        return commonOperator.del(keys);
    }

    public boolean expire(String key, long timeToLive) {
        return commonOperator.expire(key, timeToLive);
    }

    public long timeToLive(String key) {
        return commonOperator.timeToLive(key);
    }

    // ================== 1.String ==================
    public void set(String key, String value) {
        stringOperator.set(key, value);
    }

    public String get(String key) {
        return stringOperator.get(key);
    }

    public String[] mGet(String... keys) {
        return stringOperator.mGet(keys);
    }

    public void mSet(String[] keys, String[] values) {
        stringOperator.mSet(keys, values);
    }

    public int incr(String key) {
        return stringOperator.incr(key);
    }

    public int decr(String key) {
        return stringOperator.decr(key);
    }

    public Integer strLen(String key) {
        return stringOperator.strLen(key);
    }

    // ================== 2.List ==================
    public Integer lPush(String key, String... values) {
        return listOperator.lPush(key, values);
    }

    public String[] lPop(String key, int count) {
        return listOperator.lPop(key, count);
    }

    public Integer rPush(String key, String[] values) {
        return listOperator.rPush(key, values);
    }

    public String[] rPop(String key, int count) {
        return listOperator.rPop(key, count);
    }

    public Integer lLen(String key) {
        return listOperator.lLen(key);
    }

    public String lIndex(String key, int index) {
        return listOperator.lIndex(key, index);
    }

    public String[] lRange(String key, int startIndex, int endIndex) {
        return listOperator.lRange(key, startIndex, endIndex);
    }

    // ================== 3.Set ==================
    public Integer sAdd(String key, String[] values) {
        return setOperator.sAdd(key, values);
    }

    public String[] sMembers(String key) {
        return setOperator.sMembers(key);
    }

    public Integer sCard(String key) {
        return setOperator.sCard(key);
    }

    public Integer sIsMember(String key, String value) {
        return setOperator.sIsMember(key, value);
    }

    public Integer sRem(String key, String[] values) {
        return setOperator.sRem(key, values);
    }

    public String[] sPop(String key, int count) {
        return setOperator.sPop(key, count);
    }

    // ================== 4.Hash ==================
    public Integer hSet(String key, String[] fields, String[] values) {
        return hashOperator.hSet(key, fields, values);
    }

    public String hGet(String key, String field) {
        return hashOperator.hGet(key, field);
    }

    public String[] hGetAll(String key) {
        return hashOperator.hGetAll(key);
    }

    public String[] hMGet(String key, String[] hKeys) {
        return hashOperator.hMGet(key, hKeys);
    }

    public Integer hLen(String key) {
        return hashOperator.hLen(key);
    }

    public Integer hExists(String key, String hKey) {
        return hashOperator.hExists(key, hKey);
    }

    public Integer hDel(String key, String[] hKeys) {
        return hashOperator.hDel(key, hKeys);
    }

    // ================== 5.ZSet ==================
    public Integer zAdd(String key, String[] values, double[] scores) {
        return zSetOperator.zAdd(key, values, scores);
    }

    public Integer zCard(String key) {
        return zSetOperator.zCard(key);
    }

    public Integer zCount(String key, double min, double max) {
        return zSetOperator.zCount(key, min, max);
    }

    public Double zScore(String key, String value) {
        return zSetOperator.zScore(key, value);
    }

    public Integer zRank(String key, String value) {
        return zSetOperator.zRank(key, value);
    }

    public Integer zRem(String key, String[] values) {
        return zSetOperator.zRem(key, values);
    }

}
